package Shifu.MainServer.Management;

import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;


/**
 * @class Descrittore di un chunk
 * @authors vr069316
 */

public class ChunkDescriptor implements Comparable,Serializable {
	
	/* campi */
	
	/* Nome del chunk */
	private String chunkname;

	/* Nome del file del chunk */
	private String filename;
	
	/* Posizione del chunk */
	private int poschunk;
	
	/* Hash del chunk */
	private String hashchunk;

	/* Dimesione in byte del chunk */
	private long dimchunk;

	/* Lista Peer */
	private List peerslist;
	
	/* costruttore */
	
	/**
	 * Instazia un oggetto chunkDescriptor
	 * @param nome del chunk
	 * @param nome del file al quale appartiene quel chunk
	 * @param posizione del chunk
	 * @param hash del chunk
	 * @param dimesione del chunk
	 */

	public ChunkDescriptor(String chunkname,String filename,int poschunk,String hashchunk,long dimchunk) {
		
		this.chunkname = chunkname;
		this.filename = filename;
		this.poschunk = poschunk;
		this.hashchunk = hashchunk;
		this.dimchunk = dimchunk;	
		this.peerslist = new ArrayList();
	}
	
	/* metodi */
	
	/**
	 * Restituisce il nome del chunk
	 * @return chunkname, nome del chunk
	 */

	public String getChunkName() {
		return this.chunkname;
	}
	
	/**
	 * Restituisce il nome del file
	 * @return filename, nome del file del chunk
	 */

	public String getFileName() {
		return this.filename;
	}
	
	/**
	 * Restituisce il posizione del chunk
	 * @return  poschunk, posizione del chunk nel file
	 */

	public int getPoschunk() {
		return this.poschunk;
	}
	
	
	/**
	 * Restituisce l'hash del chunk
	 * @return hashchunk, hash del chunk
	 */

	public String getHashchunk() {
		return this.hashchunk;
	}


	/**
	 * Restituisce la dimensione del chunk
	 * @return dimensione del chunk
	 */

	public long getDimChunk() {
		return this.dimchunk;
	}

	/**
	 * Setta la dimensione del chunk	
	 * @param dim nuova dimensione del chunk
	 */

	public void setDimChunk(long dim) {
		this.dimchunk = dim;
	}

	
	/**
	 * Setta la posizione del chunk
	 * @param newpos, nuova posizione del chunk
	 * @throws IllegalArgumentException
	 */

	public void setPoschunk(int newpos) {
		
		if(newpos >= 0) 
			this.poschunk = newpos;
		else
			throw new IllegalArgumentException();
	}
	
	
	/**
	 * Setta la lista dei Peers che hanno questo chunk
	 * @param list lista dei Peers
	 */

	public void setPeersList(ArrayList list) {
			this.peerslist = list;
	}	

	/**
	 * Restitusce la lista dei Peers che hanno questo chunk
	 * @return la lista dei Peers	
	 */

	public List getPeersList() {
		return  this.peerslist;
	}

	/**
	 * Aggiunge un peer alla lista dei Peers che hanno questo chunk
	 * @param peer il nuovo peer da aggiungere
	 */

	public void addPeerChunk(Peer peer) {
		peerslist.add(peer);
		System.out.println("Chunk "+this.chunkname+" : Aggiunto il peer: "+peer.getId()+" al lista del chunk : "+this.getChunkName());
	}

	/**
	 * Indica se c'è un determinato peer nella lista
	 * @return true se c'è
	 */

	public boolean thereIsPeer(Peer peer) {
	 	return peerslist.contains(peer);	
	}
	

	/**
	 * Ritorna i-esimo peer della lista
	 * @return il peer richiesto
	 */

	public Peer getPeerChunk(int i) {
		return (Peer) peerslist.get(i);
	}	


	/**
	 * Rimuove un determinato peer dalla lista
	 * @param peer da rimuovere
	 */

	public void removePeerChunk(Peer peer) {

		//Controlla che il peer esista
		if(!peerslist.contains(peer)) {
			System.out.println("Chunk "+this.chunkname+" : Errore in remove : Peer non presente!");
		}
		peerslist.remove(peer);
		System.out.println("Chunk "+this.chunkname+" : Rimosso il peer: "+peer.getId()+" dalla lista del chunk : "+this.getChunkName());
	}	

	


	/**
	 * Controlla se il chunk viene prima o dopo quello passato da parametro
	 * @param cd chunkdescriptor da comparar
	 * @reutrn >0 se cd viene dopo,0 se sono uguali e <0 se cd viene prima
	 */

	public int compareTo(Object cd) {
		ChunkDescriptor cd1 = (ChunkDescriptor) cd;
		return (cd1.poschunk - this.poschunk);
	}

	/**
	 * Restituisce sotto stringa le informazioni sul ChunkDescriptor
	 * @return la stringa
	 */

	public String toString() {
		return "chunk :: num: "+this.poschunk+"| of : "+this.filename+"| chunkname : "+this.chunkname+"| hash: "+this.hashchunk;
	}


	/**
	 * Stampa a video tutti i peer che hanno questo chunk
	 */

	public void printPeers() {
		
		Iterator it = peerslist.iterator();

		while(it.hasNext()) {
			Peer val = (Peer) it.next();
			System.out.println(val.toString());
		}

	}
}
